package com.alibaba.gao.delayQueue;

import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * Title:服务类
 * </p>
 * <p>
 * Description:redis延迟消息服务类
 * </p>
 * <p>
 * Copyright: 2020~2021
 * </p>
 * <p>
 * Company/Department: EnnCloud
 * </p>
 *
 * @author zhangyiwu <b>Creation Time:</b> 2021-11-22 14:52:34
 * @since V1.0
 */
@Slf4j
@Component
public class RedisDelayQueueBizService {

    @Value("${app.id}")
    private String appId;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 添加延迟队列
     *
     * @param value
     *            队列值
     * @param delay
     *            延迟时间
     * @param timeUnit
     *            时间单位
     * @param queueCode
     *            队列键
     */
    public <T> void addDelayQueue(T value, long delay, TimeUnit timeUnit, String queueCode) {
        String queueName = this.wrapQueueName(queueCode);
        try {
            RBlockingDeque<T> blockingDeque = redissonClient.getBlockingDeque(queueName);
            RDelayedQueue<T> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
            delayedQueue.offer(value, delay, timeUnit);
            log.info("add data to delayQueue success, queueName={}, value={}, delayTime={}", queueName, value,
                timeUnit.toSeconds(delay) + "秒");
        } catch (Exception e) {
            log.error("add data to delayQueue failed.", e);
            throw new RuntimeException("add data to delayQueue failed.");
        }
    }

    /**
     * 获取延迟队列
     *
     * @param queueCode
     *            队列键
     * @return T
     * @throws InterruptedException
     *             异常信息
     */
    public <T> T getDelayQueue(String queueCode) throws Exception {
        String queueName = this.wrapQueueName(queueCode);
        RBlockingDeque<T> blockingDeque = redissonClient.getBlockingDeque(queueName);
        return blockingDeque.take();
    }

    /**
     * 封装队列名称
     *
     * @param queueCode
     *            队列名
     * @return String
     */
    private String wrapQueueName(String queueCode) {
        return appId + Separator.COLON + queueCode;
    }
}
